package zheng.interview.rpc;

import org.springframework.util.StringUtils;
import zheng.interview.RpcRequest;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Map;

/**
 * @author eric
 * @date 2021/12/25 20:57
 * @description
 */
public class ProcessorHandler implements Runnable {

    private Socket socket;

    private Map<String, Object> handlerMap;

    public ProcessorHandler(Map<String, Object> handlerMap, Socket socket) {
        this.handlerMap = handlerMap;
        this.socket = socket;
    }

    @Override
    public void run() {
        ObjectInputStream objectInputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            objectInputStream = new ObjectInputStream(socket.getInputStream());
            // 输入流中应该有哪些信息
            //  请求那个类， 方法名称， 参数
            RpcRequest rpcRequest = (RpcRequest) objectInputStream.readObject();
            Object result = invoke(rpcRequest);

            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(result);
            objectOutputStream.flush();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (objectInputStream != null) {
                try {
                    objectInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 反射调用项目中存在的接口
     *
     * @param rpcRequest 请求信息
     * @return 返回调用结果
     */
    private Object invoke(RpcRequest rpcRequest) {
        String version = rpcRequest.getVersion();
        String serviceName = rpcRequest.getClassName();
        Object service = handlerMap.get(serviceName);
        if (service == null) {
            throw new RuntimeException("service not found:" + serviceName);
        }

        if (!StringUtils.isEmpty(version)) {
            serviceName += "-" + version;
        }
        // 参数值
        Object[] args = rpcRequest.getParameters();
        // 参数类型
        Class<?>[] types = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            types[i] = args[i].getClass();
        }

        Object result = null;
        try {
            // 获取请求的类
            Class clazz = Class.forName(rpcRequest.getClassName());
            // saveUser sayHello
            Method method = clazz.getMethod(rpcRequest.getMethodName(), types);

            result = method.invoke(service, args);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return result;
    }
}
